package cn.ges.resttemplate;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.jetbrains.annotations.Nullable;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.HashMap;

/**
 * 处理所有请求外部接口的工具类 需要外部进行初始化
 *
 * @author gespent@163.com
 * @date 2018/12/25
 */
@Slf4j
public class OutHttpUtil {

    public static RestTemplate restTemplate;

    final public static String TEXT_PLAIN = "text/plain;charset=UTF-8";

    public static void initOutHttpUtil(RestTemplate restTemplate) {
        OutHttpUtil.restTemplate = restTemplate;
    }

    /**
     * 通用POST请求
     *
     * @return 返回体
     */
    public static String basePost(String data, String url, String mediaType) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType(mediaType);
        headers.setContentType(type);
        HttpEntity<String> formEntity = new HttpEntity<>(data, headers);
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, formEntity, String.class);
        return stringResponseEntity.getBody();
    }

    public static String from(String url, String filePath, String fileKey, HashMap<String, String> fromDate, @Nullable HttpHeaders headers) {
        if (headers == null) {
            headers = new HttpHeaders();
        }
        MediaType type = MediaType.parseMediaType("multipart/form-data;charset=UTF-8");
        headers.setContentType(type);

        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
        FileSystemResource fileSystemResource = new FileSystemResource(filePath);
        form.add(fileKey, fileSystemResource);

        for (String s : fromDate.keySet()) {
            form.add(s, fromDate.get(s));
        }
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(form, headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        return responseEntity.toString();
    }


    /**
     * 加载证书
     *
     * @param key  密钥
     * @param path 证书位置
     */
    private static KeyStore initCert(String key, String path) throws Exception {

        // 指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 读取本机存放的PKCS12证书文件

        try (FileInputStream stream = new FileInputStream(new File(path))) {
            // 指定PKCS12的密码
            keyStore.load(stream, key.toCharArray());
        } catch (Exception e) {
            log.error("keyStoreException", e);
        }
        return keyStore;
    }

    @SuppressWarnings("deprecation")
    private static CloseableHttpClient certificateValidation(String zfpath, String mchid) throws Exception {
        // 指定读取证书格式为PKCS12
        KeyStore keyStore = initCert(mchid, zfpath);
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray()).build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext, new String[]{"TLSv1"}, null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        return HttpClients.custom()
                .setSSLSocketFactory(sslsf).build();
    }

    public static String enterprisePayment(String url, String reqStr, String zfpath, String mchid) {
        CloseableHttpClient httpclient = null;
        InputStreamReader reader = null;
        try {
            httpclient = certificateValidation(zfpath, mchid);
            HttpPost httppost = new HttpPost(url);
            StringEntity myEntity = new StringEntity(reqStr, "UTF-8");
            httppost.setEntity(myEntity);

            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(10 * 1000)
                    .setConnectTimeout(10 * 1000)
                    .setSocketTimeout(10 * 1000)
                    .build();
            httppost.setConfig(requestConfig);

            CloseableHttpResponse response = httpclient.execute(httppost);

            final org.apache.http.HttpEntity entity = response.getEntity();
            reader = new InputStreamReader(
                    entity.getContent(), StandardCharsets.UTF_8);
            char[] buff = new char[1024];
            int length;
            StringBuilder strhuxml = new StringBuilder();
            while ((length = reader.read(buff)) != -1) {
                strhuxml.append(new String(buff, 0, length));
            }
            return strhuxml.toString();
        } catch (Exception e) {
            log.info(e.getMessage());
            e.printStackTrace();
            return "";
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
